package com.five.zhh.fiveinfive.room.util;

import cn.hutool.core.collection.CollUtil;
import com.five.zhh.fiveinfive.room.entity.pojo.Chess;

import java.util.*;

/**
 * @author 粥灰灰
 * 2025/1/28 22:23
 * 棋盘逻辑判断工具
 */
public class ChessUtil {

    public static int BOARD_SIZE = 15;

    private static final int directionLength = 4;

    // 8个方向，每两个相对方向按照下标索引对应
    private static final int[][] direction1 = new int[][]{
            {0, 1}, {1, 0}, {1, 1}, {1, -1},
    };
    private static final int[][] direction2 = new int[][]{
            {0, -1}, {-1, 0}, {-1, -1}, {-1, 1},
    };

    public static Chess[][] createNewChessboard() {
        return createNewChessboard(BOARD_SIZE);
    }

    public static Chess[][] createNewChessboard(int size) {
        return new Chess[size][size];
    }

    public static Chess[][] clear(Chess[][] chessboard) {
        if (null == chessboard) return chessboard;
        for (int i = 0; i < chessboard.length; i++) {
            Arrays.fill(chessboard[i], null);
        }
        return chessboard;
    }

    /**
     * 判断落子是否在矩形棋盘内
     */
    public static boolean isChessInBoard(final Chess[][] chessboard, int x, int y) {
        if (chessboard == null) return false;
        return x >= 0 && x < chessboard.length && y >= 0 && y < chessboard.length;
    }

    public static boolean hasChess(final Chess[][] chessboard, int x, int y) {
        if (chessboard == null) return false;
        if (!isChessInBoard(chessboard, x, y)) return false;
        return chessboard[x][y] != null;
    }

    /**
     * 利用广度优先搜索判断对应的颜色是否在一条规定线上有五个子
     *
     * @param chessboard 棋盘必须是矩阵
     * @param chess      落子点
     */
    public static boolean isWin(final Chess[][] chessboard, final Chess chess) {
        if (chessboard == null) return false;
        if (chess == null || chess.getX() == null || chess.getY() == null) return false;
        // 胜利条件，包括本次落子共5枚，所以只需要探寻四枚棋子即可
        int winnerCondition = 4;
        for (int i = 0; i < directionLength; i++) {
            List<Chess> chessInLine1 = findChessInLine(direction1[i], chessboard, chess, winnerCondition);
            List<Chess> chessInLine2 = findChessInLine(direction2[i], chessboard, chess, winnerCondition);
            if (CollUtil.isEmpty(chessInLine1) && CollUtil.isEmpty(chessInLine2)) {
                continue;
            }
            if ((chessInLine1.size() >= winnerCondition || chessInLine2.size() >= winnerCondition) || (chessInLine1.size() + chessInLine2.size() >= winnerCondition)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 从某一棋子开始沿着某一方向的一条射线搜索棋子
     *
     * @param direction  方向
     * @param board      棋盘
     * @param chess      落子点，起点
     * @param lineLength 射线长度
     * @return 棋子列表
     */
    public static List<Chess> findChessInLine(final int[] direction, final Chess[][] board, final Chess chess, int lineLength) {
        List<Chess> chessList = new ArrayList<>(lineLength);
        int moveX = chess.getX();
        int moveY = chess.getY();
        for (int i = 0; i < lineLength; i++) {
            moveX += direction[0];
            moveY += direction[1];
            Chess c = getChess(board, moveX, moveY);
            if (c == null || c.getColor() != chess.getColor()) {
                break;
            }
            chessList.add(c);
        }
        return chessList;
    }

    /**
     * 获取棋子
     * @param board 棋盘
     * @param x x坐标
     * @param y y坐标
     * @return 目标棋子
     */
    public static Chess getChess(final Chess[][] board, int x, int y) {
        if (!isChessInBoard(board, x, y)) {
            return null;
        }
        return board[x][y];
    }
}
